﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Xml;
using CarolLib;
using CarolLib.Control;
using StockMonitor.Business;
using StockMonitor.Configuration;
using StockMonitor.Helper;

namespace StockMonitor.UserControls
{
    [ModuleContract("30670B0F-CFAC-463B-B0E4-7CEBDA79910A", "交易(&R)", "限价交易")]
    public partial class UCLimitTrade : MdiUserControl
    {
        HsGateway hs = new HsGateway();

        #region Ctor.

        public UCLimitTrade()
            : base()
        {
            InitializeComponent();
        }

        public UCLimitTrade(XmlNode node)
            : this()
        {
            InitializeComponent();
        }

        #endregion

        #region Members

        bool TradeStarted = false;
        Thread threadLimitedTrade;

        #endregion

        #region EventHandler

        private void btnAddStockInPool_Click(object sender, EventArgs e)
        {
            bool isBuy = (sender as Button).Tag.ToString() == "1";

            Forms.frmEditStockInPool dlg = new Forms.frmEditStockInPool(isBuy, ReLoadPoolItemUI);
            dlg.ShowDialog();
        }

        private void btnEditStockInPool_Click(object sender, EventArgs e)
        {
            bool isBuy = (sender as Button).Tag.ToString() == "1";
            DataGridView dv = isBuy ? this.dgvBuy : this.dgvSell;
            if (dv.SelectedRows.Count == 0)
                return;
            string stockCode = dv.SelectedRows[0].Cells[0].Value.ToString();

            Forms.frmEditStockInPool dlg = new Forms.frmEditStockInPool(isBuy, stockCode, ReLoadPoolItemUI);
            dlg.ShowDialog();
        }

        private void btnDelStockInPool_Click(object sender, EventArgs e)
        {
            bool isBuy = (sender as Button).Tag.ToString() == "1";
            DataGridView dv = isBuy ? this.dgvBuy : this.dgvSell;
            if (dv.SelectedRows.Count == 0)
                return;

            string stockCode = dv.SelectedRows[0].Cells[0].Value.ToString();

            if (MessageBox.Show("您确定要删除这条配置吗？", "删除确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) != DialogResult.OK)
                return;

            LimitedStockPoolItem item = LimitedStockPool.Instance.Pool.Find(s => s.StockCode == stockCode && s.IsBuy == isBuy);
            LimitedStockPool.Instance.Pool.Remove(item);
            LimitedStockPool.Instance.Save();
            ReLoadPoolItemUI(item);
        }

        private void timerUpdateUI_Tick(object sender, EventArgs e)
        {
            ThreadPool.QueueUserWorkItem(o =>
            {
                while (!this.IsHandleCreated)
                    Thread.Sleep(100);

                this.Invoke(new Action(() =>
                {
                    this.dgvBuy.Update();
                    this.dgvSell.Refresh();
                    this.dgvSell.Update();
                    this.dgvSell.Refresh();
                }));

            });

            this.btnStartLimitedTrade.Enabled = !this.TradeStarted;
            this.btnEditSell.Enabled = !this.TradeStarted;
            this.btnAddBuy.Enabled = !this.TradeStarted;
            this.btnEditBuy.Enabled = !this.TradeStarted;
            this.btnDelBuy.Enabled = !this.TradeStarted;
            this.btnStopLimitedTrade.Enabled = this.TradeStarted;
            GlobalStatusContext.LimitedTradeStarted = this.TradeStarted;
        }

        private void btnExit_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("您确定要退出程序吗？", "退出确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)
            {
                Log.Info("退出系统");
                Application.Exit();
            }
        }

        private void btnRefresh_Click(object sender, EventArgs e)
        {
            Onload();
        }

        private void btnStartLimitedTrade_Click(object sender, EventArgs e)
        {
            StringBuilder sb = new StringBuilder("请确认以下配置信息\n");

            sb.AppendLine("\n限价触发买入股票配置：");
            LimitedStockPool.Instance.BuyPool.ForEach(s => sb.AppendLine(string.Format(" {0}({1} 买入限价:{2} 买入数量:{3} )", s.StockCode, s.StockName, s.ExchangePrice, s.ExchangeAmount)));

            sb.AppendLine("\n限价触发卖出股票配置：");
            LimitedStockPool.Instance.SellPool.ForEach(s => sb.AppendLine(string.Format(" {0}({1} 卖出限价:{2} 卖出数量:{3} ) 当前数量:{4} 可卖数量:{5} ", s.StockCode, s.StockName, s.ExchangePrice, s.ExchangeAmount, s.CurrentAmount, s.EnableAmount)));

            if (MessageBox.Show(sb.ToString(), "限价交易配置确认", MessageBoxButtons.OKCancel) == DialogResult.Cancel)
                return;

            if (GlobalStatusContext.AutoTradeStarted)
            {
                if (MessageBox.Show("自动交易正在进行中，您确定要开启限价交易吗？", "提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.Cancel)
                    return;
            }

            Log.Info("限价交易已开始");
            this.TradeStarted = true;

            threadLimitedTrade = new Thread(new ThreadStart(AutoTrade));
            threadLimitedTrade.IsBackground = true;
            threadLimitedTrade.Priority = ThreadPriority.Highest;
            threadLimitedTrade.Start();

            GlobalStatusContext.LimitedTradeStarted = this.TradeStarted;
        }

        private void btnStopLimitedTrade_Click(object sender, EventArgs e)
        {
            if (MessageBox.Show("确定要停止限价交易吗？", "确认", MessageBoxButtons.OKCancel, MessageBoxIcon.Exclamation) == DialogResult.OK)
            {
                this.TradeStarted = false;
                Log.Info("限价交易已停止");
            }
        }

        #endregion

        #region MdiUserControl Members

        public override void Onload()
        {
            this.dgvBuy.AutoGenerateColumns = false;
            this.dgvSell.AutoGenerateColumns = false;
            LoadStockPool();

            hs.Connect();

            try
            {
                RefreshStockPositionUI();
            }
            catch (HsGateway.HsCommException hsex)
            {
                Log.Exception("交易接口返回错误", hsex);
            }
            catch (Exception ex)
            {
                Log.Exception("系统错误", ex);
            }
        }

        public override void Unload()
        {
            base.Unload();
            hs.Dispose();
        }

        #endregion

        #region Methods.

        public void ReLoadPoolItemUI(LimitedStockPoolItem item)
        {
            if (item.IsBuy)
            {
                this.dgvBuy.DataSource = LimitedStockPool.Instance.BuyPool;
            }
            else
            {
                this.dgvSell.DataSource = LimitedStockPool.Instance.SellPool;
            }
        }

        public void LoadStockPool()
        {
            this.dgvBuy.DataSource = LimitedStockPool.Instance.BuyPool;
            this.dgvSell.DataSource = LimitedStockPool.Instance.SellPool;
        }

        public void RefreshStockPositionUI()
        {
            if (LimitedStockPool.Instance.RefreshStockPosition())
            {
                if (this.dgvSell.InvokeRequired)
                {
                    this.Invoke(new Action(() =>
                    {
                        this.dgvSell.DataSource = LimitedStockPool.Instance.SellPool;
                        this.dgvSell.Update();
                        this.dgvSell.Refresh();
                    }));
                }
                else
                {

                    this.dgvSell.DataSource = LimitedStockPool.Instance.SellPool;
                    this.dgvSell.Update();
                    this.dgvSell.Refresh();
                }
            }
        }

        private int ExecuteTrade(LimitedStockPoolItem stock, Enums.Signal action)
        {
            try
            {
                int result = 0;

                if (stock.IsBuy)
                {
                    //当前价格<=买入限价时，卖一买入
                    result = TradeContext.Instance.BuyOrder(stock.StockCode, stock.ExchangeAmount, Enums.PriceType.卖一);
                }
                else
                {
                    int amount = stock.ExchangeAmount;
                    if (amount > stock.EnableAmount)
                    {
                        Log.Info(stock.StockCode + "可卖数量不足，不能进行限价卖出");
                        MessageBox.Show("可卖数量不足，不能进行限价卖出!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                        return -2;
                    }
                    //当前价格<=卖出限价时，买一卖出
                    result = TradeContext.Instance.SellOrder(stock.StockCode, amount, Enums.PriceType.买一);
                }

                if (result > 0)
                {
                    ThreadPool.QueueUserWorkItem(o =>
                    {
                        Thread.Sleep(3000);
                        AuthUserContext.Instance.RefreshBalance();
                        TradeContext.Instance.UpdateTodayEntrusts();

                        Log.Info(TradeContext.Instance.TodayEntrusts.Find(t => t.EntrustNo == result).ShowResult());
                    });
                    return result;
                }
                else
                {
                    Log.Info("委托失败，错误代码：" + result.ToString());
                    return result;
                }
            }
            catch (HsGateway.HsCommException hsex)
            {
                Log.Exception("交易接口返回错误", hsex);
                return Convert.ToInt32(hsex.ErrorInfo);
            }
            catch (Exception ex)
            {
                Log.Exception("系统错误", ex);
                return -1;
            }
        }

        private void AutoTrade()
        {
            List<string> codes = LimitedStockPool.Instance.Pool.Select(s => s.StockCode).Distinct().ToList();

            while (this.TradeStarted)
            {
                bool needSavePool = false;

                Dictionary<string, StockPrice> currentPrices;
                try
                {
                    currentPrices = BusinessFactory.GetCurrentPriceProvider().BatchGetCurrentPrice(codes).ToDictionary(c => c.StockCode);
                }
                catch (Exception e)
                {
                    Log.Exception("行情价格获取失败，请检查系统配置", e);
                    Thread.Sleep(AppSettings.GetValue<int>("SignalDetectInterval", 1000, true));
                    continue;
                }

                foreach (var item in codes)
                {
                    var stockBuy = LimitedStockPool.Instance.BuyPool.Find(s => s.StockCode == item);
                    var stockSell = LimitedStockPool.Instance.SellPool.Find(s => s.StockCode == item);

                    if (stockBuy != null && stockBuy.ExchangePrice >= 0)
                    {
                        //高买：条件是 现价低于限价；当现价高于限价时，买入
                        if (stockBuy.IsEnabled && (currentPrices[item].Price >= stockBuy.ExchangePrice) && (stockBuy.ExchangeAmount > 0))//
                        {
                            needSavePool = true;

                            Log.Info(string.Format("{0}({2})自动进行限价{1}...", stockBuy.StockCode, Enums.Signal.Buy, stockBuy.StockName));
                            ExecuteTrade(stockBuy, Enums.Signal.Buy);

                            stockBuy.IsEnabled = false;
                            MessageBox.Show(string.Format("{0}({2})限价{1}交易已触发...", stockBuy.StockCode, Enums.Signal.Buy, stockBuy.StockName), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);

                        }
                    }
                    if (stockSell != null && stockSell.ExchangePrice >= 0)
                    {
                        //低卖：条件是 现价高于限价；当现价低于限价时，卖出
                        if (stockSell.IsEnabled && (currentPrices[item].Price <= stockSell.ExchangePrice) && (stockSell.ExchangeAmount > 0))//
                        {
                            needSavePool = true;

                            Log.Info(string.Format("{0}({2})自动进行限价{1}...", stockSell.StockCode, Enums.Signal.Sell, stockSell.StockName));
                            ExecuteTrade(stockSell, Enums.Signal.Sell);

                            stockSell.IsEnabled = false;
                            MessageBox.Show(string.Format("{0}({2})限价{1}交易已触发...", stockSell.StockCode, Enums.Signal.Sell, stockSell.StockName), "提示", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
                        }
                    }
                }

                if (needSavePool)
                    LimitedStockPool.Instance.Save();

                Thread.Sleep(AppSettings.GetValue<int>("SignalDetectInterval", 1000, true));
            }
        }

        #endregion

        private void dgvSell_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            foreach (DataGridViewRow row in dgvSell.Rows)
            {
                if (!LimitedStockPool.Instance.SellPool.Find(s=>s.StockCode==row.Cells[0].Value.ToString()).IsEnabled)
                {
                    row.DefaultCellStyle.ForeColor = Color.Gray;
                    row.DefaultCellStyle.BackColor = Color.LightGray;
                }
            }
        }

        private void dgvBuy_DataBindingComplete(object sender, DataGridViewBindingCompleteEventArgs e)
        {
            foreach (DataGridViewRow row in dgvBuy.Rows)
            {
                if (!LimitedStockPool.Instance.BuyPool.Find(s => s.StockCode == row.Cells[0].Value.ToString()).IsEnabled)
                {
                    row.DefaultCellStyle.ForeColor = Color.Gray;
                    row.DefaultCellStyle.BackColor = Color.LightGray;
                }
            }
        }

    }
}
